#include "AlsaAudioUtils.h"


int openAlsaAudioPcm(AlsaAudioPcm *pcm, char *name, snd_pcm_stream_t stream, int mode) {
    pcm->device = name;
    pcm->stream = stream;
    pcm->mode = mode;
    return snd_pcm_open(&pcm->pcm, pcm->device, pcm->stream, pcm->mode);
}

void closeAlsaAudioPcm(AlsaAudioPcm *pcm) {
    snd_pcm_close(pcm->pcm);
}

// 所需的PCM格式
// 所需的PCM访问权限
// 所需的PCM通道
// 所需的采样速率(单位Hz)
// 0=不允许alsa-lib重采样流, 1 =允许重采样
// latency 要求 us 的总延迟

// snd_pcm_set_params(snd_pcm_t *pcm, snd_pcm_format_t format, snd_pcm_access_t access, unsigned int channels, unsigned int rate, int soft_resample, unsigned int latency)
int setAlsaAudioPcmParam(AlsaAudioPcm *pcm, snd_pcm_format_t format, snd_pcm_access_t access, unsigned int channels, unsigned int rate, int soft_resample, unsigned int latency) {
    return snd_pcm_set_params(pcm->pcm, format, access, channels, rate, soft_resample, latency);
}

// ---------------------------------------------------------------- Readi/Writei
snd_pcm_sframes_t alsaAudioPcmRead(AlsaAudioPcm *pcm, void *buffer, snd_pcm_uframes_t size) {
    return snd_pcm_readi(pcm->pcm, buffer, size);
}
snd_pcm_sframes_t alsaAudioPcmWrite(AlsaAudioPcm *pcm, const void *buffer, snd_pcm_uframes_t size) {
    return snd_pcm_writei(pcm->pcm, buffer, size);
}
// -- 
int alsaAudioPcmRecover(AlsaAudioPcm *pcm, int err, int silent) {
    return snd_pcm_recover(pcm->pcm, err, silent);
}

// ---------------------------------------------------------------- AlsaAudioPcmSwParams
// PCM 软件配置容器


// ---------------------------------------------------------------- AlsaAudioPcmHwParams
// PCM 硬件配置容器

// 或者 setAlsaAudioPcmHwParamsMalloc
void setAlsaAudioPcmHwParamsAlloca(AlsaAudioPcmHwParams *params) {
    snd_pcm_hw_params_alloca(&params->params);
}
// 或者 setAlsaAudioPcmHwParamsAlloca
void setAlsaAudioPcmHwParamsMalloc(AlsaAudioPcmHwParams *params) {
    snd_pcm_hw_params_malloc(&params->params);
}

// 使用 AlsaAudioPcm 设备初始化 AlsaAudioPcmHwParams
int setAlsaAudioPcmHwParamsAny(AlsaAudioPcmHwParams *params, AlsaAudioPcm *pcm) {
    params->pcm = pcm;
    return snd_pcm_hw_params_any(pcm->pcm, params->params);
}

// 通过一系列 set 来设置硬件参数中的基本参数
void setAlsaAudioPcmHwParamsChannels(AlsaAudioPcmHwParams *params, int channels) {
    params->channels = channels;
    snd_pcm_hw_params_set_channels(params->pcm->pcm, params->params, params->channels);
}
void setAlsaAudioPcmHwParamsFormat(AlsaAudioPcmHwParams *params, snd_pcm_format_t format) {
    params->format = format;
    snd_pcm_hw_params_set_format(params->pcm->pcm, params->params, params->format);
}
void setAlsaAudioPcmHwParamsAccess(AlsaAudioPcmHwParams *params, snd_pcm_access_t access) {
    params->access = access;
    snd_pcm_hw_params_set_access(params->pcm->pcm, params->params, params->access);
}
void setAlsaAudioPcmHwParamsRate(AlsaAudioPcmHwParams *params, int rate, int dir) {
    params->rate = rate;
    snd_pcm_hw_params_set_rate(params->pcm->pcm, params->params, rate, dir);
}
int setAlsaAudioPcmHwParamsRateNear(AlsaAudioPcmHwParams *params, unsigned int *val, int *dir) {
    // params->rate = rate;
    return snd_pcm_hw_params_set_rate_near(params->pcm->pcm, params->params, val, dir);
}
int setAlsaAudioPcmHwParamsPeriodSizeNear(AlsaAudioPcmHwParams *params, snd_pcm_uframes_t *val, int *dir) {
    return snd_pcm_hw_params_set_period_size_near(params->pcm->pcm, params->params, val, dir);
}
int setAlsaAudioPcmHwParamsPeriodTime(AlsaAudioPcmHwParams *params, snd_pcm_uframes_t val, int dir) {
    return snd_pcm_hw_params_set_period_time(params->pcm->pcm, params->params, val, dir);
}

// get AlsaAudioPcmHwParams
int getAlsaAudioPcmHwParamsChannels(AlsaAudioPcmHwParams *params, unsigned int *channels) {
    return snd_pcm_hw_params_get_channels(params->params, channels);
}
int getAlsaAudioPcmHwParamsPeriodSize(AlsaAudioPcmHwParams *params, snd_pcm_uframes_t *frames, int *dir) {
    return snd_pcm_hw_params_get_period_size(params->params, frames, dir);
}
int getAlsaAudioPcmHwParamsPeriodTime(AlsaAudioPcmHwParams *params, unsigned int *val, int *dir) {
    return snd_pcm_hw_params_get_period_time(params->params, val, dir);
}

// apply
int  applyAlsaAudioPcmHwParams(AlsaAudioPcmHwParams *params, AlsaAudioPcm *pcm) {
    if (pcm != NULL)
        return snd_pcm_hw_params(params->pcm->pcm, params->params);
    else
        return snd_pcm_hw_params(pcm->pcm, params->params);
}
// 释放不再使用的 AlsaAudioPcmHwParams
void freeAlsaAudioPcmHwParams(AlsaAudioPcmHwParams *params) {
    snd_pcm_hw_params_free(params->params);
}

// ---------------------------------------------------------------- 